-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
solid-router-ssr-query #5310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
solid-router-ssr-query #5310
Conversation
WalkthroughIntroduces two end-to-end test projects for TanStack Solid Router and Solid Query with complete build pipelines, file-based routing, API endpoints, and Playwright tests. Additionally, creates a new Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Server
participant Router as Solid Router
participant QueryClient as Query Client
participant Provider as QueryClientProvider
Note over Server: SSR Phase
Server->>Router: Create router with QueryClient context
Server->>QueryClient: setupRouterSsrQueryIntegration(router, queryClient)
QueryClient->>QueryClient: Wrap render with QueryClientProvider
Server->>Router: renderRouterToString()
Router->>Router: Execute loaders (await ensureQueryData)
Router->>QueryClient: Fetch queries server-side
QueryClient-->>Router: Return query results
Router-->>Server: HTML + serialized cache
Note over Client: Hydration Phase
Client->>Provider: Mount QueryClientProvider with serialized cache
Provider->>QueryClient: Hydrate with server cache
Client->>Router: Hydrate router
Router->>Client: Resume from HTML (queries already available)
Client->>Client: No refetch needed if cache fresh
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Rationale: While there are 50+ files, the majority are repetitive configuration (package.json, tsconfig.json, vite.config.ts, playwright.config.ts) across two similar e2e projects. The core complexity resides in: (1) route tree generation and type-level definitions ( Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
View your CI Pipeline Execution ↗ for commit 9e9c471
☁️ Nx Cloud last updated this comment at |
More templates
@tanstack/arktype-adapter
@tanstack/directive-functions-plugin
@tanstack/eslint-plugin-router
@tanstack/history
@tanstack/nitro-v2-vite-plugin
@tanstack/react-router
@tanstack/react-router-devtools
@tanstack/react-router-ssr-query
@tanstack/react-start
@tanstack/react-start-client
@tanstack/react-start-server
@tanstack/router-cli
@tanstack/router-core
@tanstack/router-devtools
@tanstack/router-devtools-core
@tanstack/router-generator
@tanstack/router-plugin
@tanstack/router-ssr-query-core
@tanstack/router-utils
@tanstack/router-vite-plugin
@tanstack/server-functions-plugin
@tanstack/solid-router
@tanstack/solid-router-devtools
@tanstack/solid-router-ssr-query
@tanstack/solid-start
@tanstack/solid-start-client
@tanstack/solid-start-server
@tanstack/start-client-core
@tanstack/start-plugin-core
@tanstack/start-server-core
@tanstack/start-static-server-functions
@tanstack/start-storage-context
@tanstack/valibot-adapter
@tanstack/virtual-file-routes
@tanstack/zod-adapter
commit: |
e2e737a
to
197bd86
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🧹 Nitpick comments (23)
e2e/solid-start/basic-solid-query/src/utils/seo.ts (1)
1-6
: Add explicit return type annotation.For better type safety and IDE support, add an explicit return type annotation to the function.
Apply this diff to add a return type:
+type MetaTag = + | { title: string } + | { name: string; content: string | undefined } + -export function seo(params: { +export function seo(params: { title: string description?: string keywords?: string image?: string -}) { +}): MetaTag[] {As per coding guidelines.
e2e/solid-start/basic-solid-query/src/components/NotFound.tsx (2)
11-16
: Consider differentiating the button styling for better visual hierarchy.Both action buttons use the same
bg-cyan-600
color class. Other similar NotFound components in the codebase (e.g.,examples/solid/start-basic/src/components/NotFound.tsx
ande2e/solid-start/server-routes/src/components/NotFound.tsx
) use distinct colors (bg-emerald-500
for "Go back" andbg-cyan-600
for "Start Over") to provide visual differentiation between the actions.Apply this diff to match the pattern used elsewhere:
<button onClick={() => window.history.back()} - class="bg-cyan-600 text-white px-2 py-1 rounded uppercase font-black text-sm" + class="bg-emerald-500 text-white px-2 py-1 rounded uppercase font-black text-sm" > Go back </button>
4-26
: Consider adding a data-testid attribute for e2e testing.The similar NotFound component in
e2e/solid-start/server-routes/src/components/NotFound.tsx
includesdata-testid="default-not-found-component"
on the container div, which facilitates more reliable e2e test assertions. Since this is also an e2e test project, adding a test identifier would improve testability.Apply this diff:
export function NotFound(props?: { children?: JSX.Element }) { return ( - <div class="space-y-2 p-2"> + <div class="space-y-2 p-2" data-testid="default-not-found-component"> <div> {props?.children || 'The page you are looking for does not exist.'} </div>e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx (1)
1-4
: Consider using a top-level type-only import for consistency.ESLint flags the inline type specifier. While functional, separating type imports aligns with the
import/consistent-type-specifier-style
rule.Apply this diff:
import { ErrorComponent, - type ErrorComponentProps, } from '@tanstack/solid-router' +import type { ErrorComponentProps } from '@tanstack/solid-router'e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts (3)
18-23
: Use template literal and add a timeout to reduce flakinessSmall cleanup and resilience: avoid string concat and set a short timeout on the request.
- const res = await axios.get<User>(`${queryURL}/users/` + params.id) + const res = await axios.get<User>(`${queryURL}/users/${params.id}`, { timeout: 5000 })
24-27
: Return upstream status when available; gate noisy logsDifferentiate 4xx vs 5xx to aid debugging, and avoid noisy console.error in green paths.
- } catch (e) { - console.error(e) - return json({ error: 'User not found' }, { status: 404 }) - } + } catch (e: any) { + if (import.meta.env.MODE !== 'test') console.error(e) + const status = e?.response?.status ?? 500 + const body = status === 404 ? { error: 'User not found' } : { error: 'Request failed' } + return json(body, { status }) + }
6-10
: Environment variables are consistently defined in e2e config; refactor improves robustnessVite uses dotenv to load additional environment variables from .env files, and the script output confirms that
VITE_NODE_ENV
andVITE_EXTERNAL_PORT
are explicitly set in all playwright configs (both viacommand:
shell environment andenv:
object properties). The code functions correctly within the e2e test harness.However, the refactor suggestion remains valid as a defensive improvement. While the current setup works, adding fallbacks (using
MODE
as a standard Vite alternative and defaulting the port) hardens against misconfiguration outside the normal playwright execution path.-let queryURL = 'https://jsonplaceholder.typicode.com' - -if (import.meta.env.VITE_NODE_ENV === 'test') { - queryURL = `http://localhost:${import.meta.env.VITE_EXTERNAL_PORT}` -} +const isTest = import.meta.env.VITE_NODE_ENV === 'test' || import.meta.env.MODE === 'test' +const extPort = import.meta.env.VITE_EXTERNAL_PORT ?? '3001' +const queryURL = isTest ? `http://localhost:${extPort}` : 'https://jsonplaceholder.typicode.com'e2e/solid-start/basic-solid-query/package.json (1)
1-37
: Switch internal deps to workspace:*; use srvx directly; move Vite to devDependenciesThe codebase uses
workspace:^
for internal packages, but guidelines requireworkspace:*
. Additionally, srvx is available in devDependencies and Vite should move there since it's a build tool."dependencies": { "@tanstack/solid-query": "^5.66.0", "@tanstack/solid-query-devtools": "^5.66.0", - "@tanstack/solid-router": "workspace:^", - "@tanstack/solid-router-devtools": "workspace:^", - "@tanstack/solid-router-ssr-query": "workspace:^", - "@tanstack/solid-start": "workspace:^", + "@tanstack/solid-router": "workspace:*", + "@tanstack/solid-router-devtools": "workspace:*", + "@tanstack/solid-router-ssr-query": "workspace:*", + "@tanstack/solid-start": "workspace:*", "solid-js": "^1.9.5", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "vite": "^7.1.7" }, "devDependencies": { + "vite": "^7.1.7", "@playwright/test": "^1.50.1",And update the start script (line 11):
- "start": "pnpx srvx --prod -s ../client dist/server/server.js", + "start": "srvx --prod -s ../client dist/server/server.js",e2e/solid-start/query-integration/package.json (1)
1-36
: Standardize workspace: protocol, move build-time dependencies, and make scripts hermetic*
- Use workspace:* for internal packages per guidelines
- Add srvx as devDependency (start script depends on it) and remove pnpx for reproducibility
- Move Vite to devDependencies (build-time tool, not runtime)
Apply:
@@ "dependencies": { "@tanstack/solid-query": "^5.66.0", "@tanstack/solid-query-devtools": "^5.66.0", - "@tanstack/solid-router": "workspace:^", - "@tanstack/solid-router-devtools": "workspace:^", - "@tanstack/solid-router-ssr-query": "workspace:^", - "@tanstack/solid-start": "workspace:^", + "@tanstack/solid-router": "workspace:*", + "@tanstack/solid-router-devtools": "workspace:*", + "@tanstack/solid-router-ssr-query": "workspace:*", + "@tanstack/solid-start": "workspace:*", "solid-js": "^1.9.5", "tailwind-merge": "^2.6.0", - "vite": "^7.1.7", "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", - "@tanstack/router-e2e-utils": "workspace:^", + "@tanstack/router-e2e-utils": "workspace:*", "@types/node": "^22.10.2", "autoprefixer": "^10.4.20", "postcss": "^8.5.1", + "srvx": "^0.8.6", "tailwindcss": "^3.4.17", "typescript": "^5.7.2", + "vite": "^7.1.7", "vite-plugin-solid": "^2.11.8", "vite-tsconfig-paths": "^5.1.4" }Update script:
- "start": "pnpx srvx --prod -s ../client dist/server/server.js", + "start": "srvx --prod -s ../client dist/server/server.js",e2e/solid-start/basic-solid-query/tests/app.spec.ts (1)
7-7
: Consider using complete text or data-testid for more stable test selectors.The link text "sunt aut facere repe" appears truncated mid-word, which could make the test fragile if the display text changes slightly. Consider using the complete text or a data-testid attribute for more reliable element selection.
e2e/solid-start/query-integration/src/queryOptions.ts (1)
6-11
: Optionally support AbortSignal to avoid dangling timers on cancellations.Not required for e2e, but cheap to add for best practice.
- queryFn: async () => { + queryFn: async ({ signal }) => { console.log('fetching query data') - await new Promise<void>((resolve) => { - setTimeout(resolve, 500) - }) + await new Promise<void>((resolve, reject) => { + const id = setTimeout(resolve, 500) + signal?.addEventListener('abort', () => { + clearTimeout(id) + reject(new DOMException('Aborted', 'AbortError')) + }) + })e2e/solid-start/query-integration/src/routes/loader-fetchQuery/$type.tsx (1)
3-15
: Tighten typings: zod import + loader return type (avoidas any
).
- Use named import for zod to avoid relying on synthetic default imports.
- Let the loader return string | undefined and drop the cast.
-import z from 'zod' +import { z } from 'zod' @@ -export const Route = createFileRoute('/loader-fetchQuery/$type')({ +export const Route = createFileRoute('/loader-fetchQuery/$type')({ @@ - loader: async ({ context, params }) => { + // Loader returns the string for 'sync', otherwise undefined + loader: async ({ context, params }): Promise<string | undefined> => { await context.queryClient.ensureQueryData(context.queryOptions) if (params.type === 'sync') { return context.queryClient.getQueryData( context.queryOptions.queryKey, ) as string } - return undefined as any + return undefined }, }) @@ - const query = useQuery(() => { - return makeQueryOptions(`loader-fetchQuery-${params().type}`) - }) + const query = useQuery(() => + makeQueryOptions(`loader-fetchQuery-${params().type}`), + )Also applies to: 19-27, 33-35
e2e/solid-start/basic-solid-query/src/routes/users.tsx (1)
20-25
: Optional: avoid rebuilding the array each render.Not a blocker, but you can memoize the list or render the “Non-existent User” as a separate item.
-import { For } from 'solid-js' +import { For, createMemo } from 'solid-js' @@ function UsersComponent() { const usersQuery = useQuery(() => usersQueryOptions()) + const users = createMemo(() => usersQuery.data ?? []) @@ - <For - each={[ - ...(usersQuery.data ?? []), - { id: 'i-do-not-exist', name: 'Non-existent User', email: '' }, - ]} - > + <For each={users()}> {(user) => ( <li class="whitespace-nowrap"> @@ )} </For> + <li class="whitespace-nowrap"> + <Link + to="/users/$userId" + params={{ userId: 'i-do-not-exist' }} + class="block py-1 text-blue-800 hover:text-blue-600" + activeProps={{ class: 'text-black font-bold' }} + > + <div>Non-existent User</div> + </Link> + </li>e2e/solid-start/basic-solid-query/src/routes/__root.tsx (3)
78-78
: Add lang attribute for accessibility.Helps screen readers and SEO.
- <html> + <html lang="en">
28-33
: Open Graph tags should use "property", not "name".seo() returns og:* entries with name; prefer property for OG crawlers.
Apply in src/utils/seo.ts:
- { name: 'og:type', content: 'website' }, - { name: 'og:title', content: title }, - { name: 'og:description', content: description }, + { property: 'og:type', content: 'website' }, + { property: 'og:title', content: title }, + { property: 'og:description', content: description }, @@ - { name: 'og:image', content: image }, + { property: 'og:image', content: image },
9-9
: Optional: import the stable alias for devtools.Prefer TanStackRouterDevtools for consistency with examples.
-import { TanStackRouterDevtoolsInProd } from '@tanstack/solid-router-devtools' +import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' @@ - <TanStackRouterDevtoolsInProd position="bottom-right" /> + <TanStackRouterDevtools position="bottom-right" />packages/solid-router-ssr-query/src/index.tsx (1)
12-31
: Make wrapper idempotent and document options.Repeated setup currently nests providers. Add a one-time guard and brief JSDoc.
+/** + * Wire up SSR integration between Solid Router and Solid Query. + * + * By default, wraps the router's Wrap with a QueryClientProvider. + * Set `wrapQueryClient` to `false` to opt out. + */ export function setupRouterSsrQueryIntegration<TRouter extends AnyRouter>( opts: Options<TRouter>, ) { setupCoreRouterSsrQueryIntegration(opts) - if (opts.wrapQueryClient === false) { + // Prevent double-wrapping if called more than once + const WRAPPED = Symbol.for('@tanstack/solid-router-ssr-query:wrapped') + if ((opts.router as any)[WRAPPED]) { + return + } + + if (opts.wrapQueryClient === false) { return } const OGWrap = opts.router.options.Wrap || ((props: { children: JSX.Element }) => props.children) opts.router.options.Wrap = (props) => { return ( <QueryClientProvider client={opts.queryClient}> <OGWrap>{props.children}</OGWrap> </QueryClientProvider> ) } + ;(opts.router as any)[WRAPPED] = true }e2e/solid-start/basic-solid-query/src/routes/posts.tsx (1)
31-33
: Ensure route param is a string.Route params are strings; coerce numeric ids to avoid TS/narrowing issues.
- params={{ - postId: post.id, - }} + params={{ postId: String(post.id) }}e2e/solid-start/query-integration/playwright.config.ts (1)
23-28
: Make webServer command cross‑platform.Env var syntax and quoted values break on Windows. Use cross-env (or Playwright env option).
- command: `VITE_NODE_ENV="test" VITE_EXTERNAL_PORT=${EXTERNAL_PORT} VITE_SERVER_PORT=${PORT} pnpm build && VITE_NODE_ENV="test" VITE_EXTERNAL_PORT=${EXTERNAL_PORT} PORT=${PORT} VITE_SERVER_PORT=${PORT} pnpm start`, + command: `cross-env VITE_NODE_ENV=test VITE_EXTERNAL_PORT=${EXTERNAL_PORT} VITE_SERVER_PORT=${PORT} pnpm build && cross-env VITE_NODE_ENV=test VITE_EXTERNAL_PORT=${EXTERNAL_PORT} PORT=${PORT} VITE_SERVER_PORT=${PORT} pnpm start`,Alternatively, set webServer.env and simplify the command.
e2e/solid-start/query-integration/src/routes/__root.tsx (2)
28-28
: Add lang attribute on html.Improves a11y and SEO.
- <html> + <html lang="en">
15-22
: Optional: add viewport meta.Consistent with the other root; helps responsive behavior.
head: () => ({ meta: [ { charset: 'utf-8', }, + { name: 'viewport', content: 'width=device-width, initial-scale=1' }, ],
packages/solid-router-ssr-query/package.json (1)
71-79
: Align dev vs peer version ranges for Solid Query.Use the same minimum to avoid subtle type divergence.
- "@tanstack/solid-query": ">=5.66.0", + "@tanstack/solid-query": ">=5.66.2",e2e/solid-start/basic-solid-query/src/utils/users.tsx (1)
15-25
: Optional: set a short staleTime to reduce e2e flakiness.export const usersQueryOptions = () => queryOptions({ queryKey: ['users'], + staleTime: 5_000,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (51)
e2e/solid-start/basic-solid-query/package.json
(1 hunks)e2e/solid-start/basic-solid-query/playwright.config.ts
(1 hunks)e2e/solid-start/basic-solid-query/postcss.config.mjs
(1 hunks)e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/components/NotFound.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routeTree.gen.ts
(1 hunks)e2e/solid-start/basic-solid-query/src/router.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/__root.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/api.users.ts
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/deferred.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/index.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/posts.index.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/posts.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/users.index.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/routes/users.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/styles/app.css
(1 hunks)e2e/solid-start/basic-solid-query/src/utils/posts.tsx
(1 hunks)e2e/solid-start/basic-solid-query/src/utils/seo.ts
(1 hunks)e2e/solid-start/basic-solid-query/src/utils/users.tsx
(1 hunks)e2e/solid-start/basic-solid-query/tailwind.config.mjs
(1 hunks)e2e/solid-start/basic-solid-query/tests/app.spec.ts
(1 hunks)e2e/solid-start/basic-solid-query/tests/setup/global.setup.ts
(1 hunks)e2e/solid-start/basic-solid-query/tests/setup/global.teardown.ts
(1 hunks)e2e/solid-start/basic-solid-query/tsconfig.json
(1 hunks)e2e/solid-start/basic-solid-query/vite.config.ts
(1 hunks)e2e/solid-start/query-integration/package.json
(1 hunks)e2e/solid-start/query-integration/playwright.config.ts
(1 hunks)e2e/solid-start/query-integration/postcss.config.mjs
(1 hunks)e2e/solid-start/query-integration/src/queryOptions.ts
(1 hunks)e2e/solid-start/query-integration/src/routeTree.gen.ts
(1 hunks)e2e/solid-start/query-integration/src/router.tsx
(1 hunks)e2e/solid-start/query-integration/src/routes/__root.tsx
(1 hunks)e2e/solid-start/query-integration/src/routes/index.tsx
(1 hunks)e2e/solid-start/query-integration/src/routes/loader-fetchQuery/$type.tsx
(1 hunks)e2e/solid-start/query-integration/src/routes/useQuery.tsx
(1 hunks)e2e/solid-start/query-integration/src/styles/app.css
(1 hunks)e2e/solid-start/query-integration/tailwind.config.mjs
(1 hunks)e2e/solid-start/query-integration/tests/app.spec.ts
(1 hunks)e2e/solid-start/query-integration/tsconfig.json
(1 hunks)e2e/solid-start/query-integration/vite.config.ts
(1 hunks)package.json
(1 hunks)packages/solid-router-ssr-query/README.md
(1 hunks)packages/solid-router-ssr-query/eslint.config.js
(1 hunks)packages/solid-router-ssr-query/package.json
(1 hunks)packages/solid-router-ssr-query/src/index.tsx
(1 hunks)packages/solid-router-ssr-query/tsconfig.json
(1 hunks)packages/solid-router-ssr-query/vite.config.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
e2e/solid-start/query-integration/src/router.tsx
e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx
e2e/solid-start/basic-solid-query/src/routes/users.index.tsx
e2e/solid-start/basic-solid-query/src/components/NotFound.tsx
e2e/solid-start/basic-solid-query/src/utils/posts.tsx
e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx
e2e/solid-start/query-integration/src/routes/loader-fetchQuery/$type.tsx
e2e/solid-start/basic-solid-query/src/utils/seo.ts
e2e/solid-start/basic-solid-query/src/routes/posts.index.tsx
e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx
e2e/solid-start/basic-solid-query/src/routes/deferred.tsx
e2e/solid-start/basic-solid-query/src/routes/api.users.ts
e2e/solid-start/basic-solid-query/src/routes/users.tsx
e2e/solid-start/query-integration/src/queryOptions.ts
e2e/solid-start/basic-solid-query/src/router.tsx
e2e/solid-start/basic-solid-query/tests/setup/global.setup.ts
e2e/solid-start/query-integration/src/routes/index.tsx
e2e/solid-start/query-integration/src/routes/useQuery.tsx
e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts
e2e/solid-start/basic-solid-query/src/routes/__root.tsx
e2e/solid-start/query-integration/tests/app.spec.ts
e2e/solid-start/basic-solid-query/src/routes/index.tsx
e2e/solid-start/query-integration/src/routes/__root.tsx
packages/solid-router-ssr-query/vite.config.ts
e2e/solid-start/basic-solid-query/src/utils/users.tsx
e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx
e2e/solid-start/basic-solid-query/src/routes/posts.tsx
e2e/solid-start/basic-solid-query/tests/setup/global.teardown.ts
e2e/solid-start/query-integration/src/routeTree.gen.ts
e2e/solid-start/query-integration/playwright.config.ts
e2e/solid-start/query-integration/vite.config.ts
e2e/solid-start/basic-solid-query/playwright.config.ts
packages/solid-router-ssr-query/src/index.tsx
e2e/solid-start/basic-solid-query/tests/app.spec.ts
e2e/solid-start/basic-solid-query/src/routeTree.gen.ts
e2e/solid-start/basic-solid-query/vite.config.ts
e2e/**
📄 CodeRabbit inference engine (AGENTS.md)
Store end-to-end tests under the e2e/ directory
Files:
e2e/solid-start/query-integration/src/router.tsx
e2e/solid-start/basic-solid-query/postcss.config.mjs
e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx
e2e/solid-start/basic-solid-query/src/routes/users.index.tsx
e2e/solid-start/basic-solid-query/src/components/NotFound.tsx
e2e/solid-start/basic-solid-query/tailwind.config.mjs
e2e/solid-start/basic-solid-query/src/utils/posts.tsx
e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx
e2e/solid-start/query-integration/src/routes/loader-fetchQuery/$type.tsx
e2e/solid-start/basic-solid-query/src/utils/seo.ts
e2e/solid-start/basic-solid-query/src/routes/posts.index.tsx
e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx
e2e/solid-start/basic-solid-query/src/routes/deferred.tsx
e2e/solid-start/basic-solid-query/src/styles/app.css
e2e/solid-start/basic-solid-query/src/routes/api.users.ts
e2e/solid-start/basic-solid-query/src/routes/users.tsx
e2e/solid-start/query-integration/src/styles/app.css
e2e/solid-start/query-integration/src/queryOptions.ts
e2e/solid-start/basic-solid-query/src/router.tsx
e2e/solid-start/basic-solid-query/tests/setup/global.setup.ts
e2e/solid-start/query-integration/src/routes/index.tsx
e2e/solid-start/query-integration/src/routes/useQuery.tsx
e2e/solid-start/query-integration/postcss.config.mjs
e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts
e2e/solid-start/basic-solid-query/src/routes/__root.tsx
e2e/solid-start/query-integration/tests/app.spec.ts
e2e/solid-start/basic-solid-query/src/routes/index.tsx
e2e/solid-start/query-integration/src/routes/__root.tsx
e2e/solid-start/basic-solid-query/tsconfig.json
e2e/solid-start/basic-solid-query/src/utils/users.tsx
e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx
e2e/solid-start/basic-solid-query/src/routes/posts.tsx
e2e/solid-start/basic-solid-query/tests/setup/global.teardown.ts
e2e/solid-start/query-integration/src/routeTree.gen.ts
e2e/solid-start/query-integration/tsconfig.json
e2e/solid-start/query-integration/playwright.config.ts
e2e/solid-start/query-integration/tailwind.config.mjs
e2e/solid-start/query-integration/vite.config.ts
e2e/solid-start/basic-solid-query/playwright.config.ts
e2e/solid-start/query-integration/package.json
e2e/solid-start/basic-solid-query/tests/app.spec.ts
e2e/solid-start/basic-solid-query/src/routeTree.gen.ts
e2e/solid-start/basic-solid-query/package.json
e2e/solid-start/basic-solid-query/vite.config.ts
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
e2e/solid-start/basic-solid-query/src/routes/users.index.tsx
e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx
e2e/solid-start/query-integration/src/routes/loader-fetchQuery/$type.tsx
e2e/solid-start/basic-solid-query/src/routes/posts.index.tsx
e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx
e2e/solid-start/basic-solid-query/src/routes/deferred.tsx
e2e/solid-start/basic-solid-query/src/routes/api.users.ts
e2e/solid-start/basic-solid-query/src/routes/users.tsx
e2e/solid-start/query-integration/src/routes/index.tsx
e2e/solid-start/query-integration/src/routes/useQuery.tsx
e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts
e2e/solid-start/basic-solid-query/src/routes/__root.tsx
e2e/solid-start/basic-solid-query/src/routes/index.tsx
e2e/solid-start/query-integration/src/routes/__root.tsx
e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx
e2e/solid-start/basic-solid-query/src/routes/posts.tsx
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
package.json
packages/solid-router-ssr-query/package.json
e2e/solid-start/query-integration/package.json
e2e/solid-start/basic-solid-query/package.json
🧠 Learnings (2)
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript in strict mode with extensive type safety across the codebase
Applied to files:
e2e/solid-start/basic-solid-query/tsconfig.json
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
PR: TanStack/router#5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.
Applied to files:
e2e/solid-start/query-integration/src/routeTree.gen.ts
🧬 Code graph analysis (28)
e2e/solid-start/query-integration/src/router.tsx (2)
e2e/solid-start/basic-solid-query/src/router.tsx (1)
getRouter
(8-30)packages/solid-router-ssr-query/src/index.tsx (1)
setupRouterSsrQueryIntegration
(12-32)
e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx (1)
examples/solid/start-basic/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(10-53)
e2e/solid-start/basic-solid-query/src/routes/users.index.tsx (2)
e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx (1)
Route
(8-17)e2e/solid-start/basic-solid-query/src/routes/users.tsx (1)
Route
(7-12)
e2e/solid-start/basic-solid-query/src/components/NotFound.tsx (2)
examples/solid/start-basic/src/components/NotFound.tsx (1)
NotFound
(3-25)e2e/solid-start/server-routes/src/components/NotFound.tsx (1)
NotFound
(3-25)
e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx (4)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (1)
Route
(16-66)e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx (2)
Route
(5-11)PostErrorComponent
(13-15)e2e/solid-start/basic-solid-query/src/routes/posts.tsx (1)
Route
(6-12)e2e/solid-start/basic-solid-query/src/utils/posts.tsx (1)
postQueryOptions
(22-33)
e2e/solid-start/query-integration/src/routes/loader-fetchQuery/$type.tsx (1)
e2e/solid-start/query-integration/src/queryOptions.ts (1)
makeQueryOptions
(3-16)
e2e/solid-start/basic-solid-query/src/utils/seo.ts (1)
examples/solid/start-basic/src/utils/seo.ts (1)
title
(1-33)
e2e/solid-start/basic-solid-query/src/routes/posts.index.tsx (3)
e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx (1)
Route
(5-11)e2e/solid-start/basic-solid-query/src/routes/posts.tsx (1)
Route
(6-12)e2e/solid-start/basic-solid-query/src/routes/users.index.tsx (1)
Route
(3-5)
e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx (4)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (1)
Route
(16-66)e2e/solid-start/basic-solid-query/src/routes/posts.tsx (1)
Route
(6-12)e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx (1)
Route
(6-21)e2e/solid-start/basic-solid-query/src/utils/posts.tsx (1)
postQueryOptions
(22-33)
e2e/solid-start/basic-solid-query/src/routes/deferred.tsx (2)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (1)
Route
(16-66)e2e/solid-start/basic-solid-query/src/routes/posts.tsx (1)
Route
(6-12)
e2e/solid-start/basic-solid-query/src/routes/api.users.ts (2)
e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts (1)
Route
(12-31)e2e/solid-start/basic-solid-query/src/utils/users.tsx (1)
User
(4-8)
e2e/solid-start/basic-solid-query/src/routes/users.tsx (5)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (1)
Route
(16-66)e2e/solid-start/basic-solid-query/src/routes/api.users.ts (1)
Route
(12-25)e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts (1)
Route
(12-31)e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx (1)
Route
(8-17)e2e/solid-start/basic-solid-query/src/utils/users.tsx (1)
usersQueryOptions
(15-25)
e2e/solid-start/basic-solid-query/src/router.tsx (4)
e2e/solid-start/query-integration/src/router.tsx (1)
getRouter
(6-26)e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(6-8)e2e/solid-start/basic-solid-query/src/components/NotFound.tsx (1)
NotFound
(4-26)packages/solid-router-ssr-query/src/index.tsx (1)
setupRouterSsrQueryIntegration
(12-32)
e2e/solid-start/basic-solid-query/tests/setup/global.setup.ts (3)
scripts/set-ts-version.js (1)
packageJson
(33-33)e2e/solid-router/basic-solid-query-file-based/tests/setup/global.setup.ts (1)
setup
(4-6)e2e/solid-router/basic-solid-query/tests/setup/global.setup.ts (1)
setup
(4-6)
e2e/solid-start/query-integration/src/routes/index.tsx (3)
e2e/solid-start/basic-solid-query/src/routes/index.tsx (1)
Route
(3-5)e2e/solid-start/query-integration/src/routes/__root.tsx (1)
Route
(12-24)e2e/solid-start/query-integration/src/routes/useQuery.tsx (1)
Route
(7-12)
e2e/solid-start/query-integration/src/routes/useQuery.tsx (3)
e2e/solid-start/query-integration/src/queryOptions.ts (1)
makeQueryOptions
(3-16)e2e/solid-start/query-integration/src/routes/__root.tsx (1)
Route
(12-24)e2e/solid-start/query-integration/src/routes/loader-fetchQuery/$type.tsx (1)
Route
(6-28)
e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts (2)
e2e/solid-start/basic-solid-query/src/routes/api.users.ts (1)
Route
(12-25)e2e/solid-start/basic-solid-query/src/utils/users.tsx (1)
User
(4-8)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (6)
e2e/solid-start/query-integration/src/routes/__root.tsx (1)
Route
(12-24)e2e/solid-start/basic-solid-query/src/utils/seo.ts (1)
seo
(1-30)e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx (1)
DefaultCatchBoundary
(6-8)e2e/solid-start/basic-solid-query/src/components/NotFound.tsx (1)
NotFound
(4-26)packages/router-devtools/src/index.tsx (1)
TanStackRouterDevtoolsInProd
(5-5)examples/solid/basic-solid-query-file-based/src/routes/__root.tsx (1)
RootComponent
(25-71)
e2e/solid-start/basic-solid-query/src/routes/index.tsx (2)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (1)
Route
(16-66)e2e/solid-start/query-integration/src/routes/index.tsx (1)
Route
(3-5)
e2e/solid-start/query-integration/src/routes/__root.tsx (3)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (1)
Route
(16-66)packages/router-devtools/src/index.tsx (1)
TanStackRouterDevtoolsInProd
(5-5)examples/solid/start-basic/src/routes/__root.tsx (1)
RootDocument
(59-121)
packages/solid-router-ssr-query/vite.config.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx (3)
e2e/solid-start/basic-solid-query/src/routes/api/users.$id.ts (1)
Route
(12-31)e2e/solid-start/basic-solid-query/src/utils/users.tsx (1)
userQueryOptions
(27-37)e2e/solid-start/basic-solid-query/src/components/NotFound.tsx (1)
NotFound
(4-26)
e2e/solid-start/basic-solid-query/src/routes/posts.tsx (3)
e2e/solid-start/basic-solid-query/src/routes/__root.tsx (1)
Route
(16-66)e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx (1)
Route
(5-11)e2e/solid-start/basic-solid-query/src/utils/posts.tsx (1)
postsQueryOptions
(10-20)
e2e/solid-start/basic-solid-query/tests/setup/global.teardown.ts (7)
e2e/solid-router/basic-solid-query-file-based/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/solid-router/basic-solid-query/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/solid-router/basic-file-based/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/solid-router/basic-file-based-code-splitting/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/solid-router/basic-virtual-named-export-config-file-based/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/solid-start/basic/tests/setup/global.teardown.ts (1)
teardown
(4-6)e2e/solid-router/basic-virtual-file-based/tests/setup/global.teardown.ts (1)
teardown
(4-6)
e2e/solid-start/query-integration/src/routeTree.gen.ts (1)
e2e/solid-start/query-integration/src/router.tsx (1)
getRouter
(6-26)
e2e/solid-start/basic-solid-query/playwright.config.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
packages/solid-router-ssr-query/src/index.tsx (1)
packages/router-ssr-query-core/src/index.ts (2)
RouterSsrQueryOptions
(12-23)setupCoreRouterSsrQueryIntegration
(30-160)
e2e/solid-start/basic-solid-query/src/routeTree.gen.ts (1)
e2e/solid-start/basic-solid-query/src/router.tsx (1)
getRouter
(8-30)
🪛 ESLint
e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx
[error] 3-3: Prefer using a top-level type-only import instead of inline type specifiers.
(import/consistent-type-specifier-style)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Test
- GitHub Check: Preview
🔇 Additional comments (39)
e2e/solid-start/basic-solid-query/tsconfig.json (1)
1-24
: Configuration looks solid—well-aligned with TypeScript and SolidJS best practices.This tsconfig correctly sets up strict mode with extensive type safety (per coding guidelines), SolidJS JSX support (
jsxImportSource
,jsx: "preserve"
), and Vite-compatible module resolution (moduleResolution: "Bundler"
,noEmit
). The path alias pattern (~/*
→./src/*
) is idiomatic and will support clean imports in the test project. The ES2022 target and DOM library support are appropriate for a modern SSR setup.e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx (4)
1-4
: LGTM!All imports are appropriately used throughout the file.
6-6
: Verify the underscore in the route path.The route path
/posts_/$postId/deep
uses an underscore, creating a separate top-level segment rather than nesting under/posts
. The sibling route atposts.$postId.tsx
uses/posts/$postId
without an underscore. If this route should be nested under the posts section, the path should be/posts/$postId/deep
instead.If the underscore is intentional (e.g., testing edge cases with underscores in paths), this is fine. Otherwise, consider this fix:
-export const Route = createFileRoute('/posts_/$postId/deep')({ +export const Route = createFileRoute('/posts/$postId/deep')({Note: You would also need to rename the file from
posts_.$postId.deep.tsx
toposts.$postId.deep.tsx
.
7-20
: LGTM!The loader, head, and error handling configuration follow the correct SSR patterns for TanStack Router and Solid Query integration. The data is properly ensured on the server, and the title is correctly passed to the head meta for SEO.
23-36
: LGTM!The component correctly implements the SSR + client-side hydration pattern:
- Uses reactive params accessor correctly for Solid
- Query factory function ensures reactivity when params change
- Optional chaining provides safe access to query data
- Data is prefetched in the loader, so the component picks up cached data without a waterfall
package.json (1)
99-99
: LGTM!The workspace override for
@tanstack/solid-router-ssr-query
correctly follows the established pattern and uses theworkspace:*
protocol as required by coding guidelines.e2e/solid-start/query-integration/src/styles/app.css (1)
1-8
: LGTM!Standard Tailwind CSS setup with appropriate base styling. The configuration aligns with the PostCSS and Tailwind configs in the project.
e2e/solid-start/query-integration/postcss.config.mjs (1)
1-6
: LGTM!Standard PostCSS configuration for Tailwind CSS processing with autoprefixer. The setup is correct and aligns with the Tailwind configuration in the project.
e2e/solid-start/basic-solid-query/postcss.config.mjs (1)
1-6
: LGTM!Standard PostCSS configuration for Tailwind CSS processing. The setup is appropriate for this independent e2e test project.
e2e/solid-start/query-integration/tsconfig.json (1)
1-24
: LGTM!The TypeScript configuration is well-structured with strict mode enabled (as required by coding guidelines), appropriate Solid.js settings, and standard Vite/ESNext module resolution. The path alias and compiler options are correctly configured for the e2e test environment.
e2e/solid-start/basic-solid-query/src/components/DefaultCatchBoundary.tsx (1)
6-8
: LGTM!The component correctly wraps and forwards props to the
ErrorComponent
from@tanstack/solid-router
. This simplified implementation is appropriate for the e2e test scenario.e2e/solid-start/basic-solid-query/vite.config.ts (1)
1-14
: LGTM!The Vite configuration correctly wires up the SSR-enabled Solid Start plugin stack. The plugins are properly ordered with TypeScript path resolution, TanStack Start plugin, and Solid plugin with SSR enabled. This setup is appropriate for the e2e Solid Start scenario.
e2e/solid-start/basic-solid-query/tailwind.config.mjs (1)
1-8
: LGTMMinimal Tailwind config is fine for e2e. If you add MDX or external template paths later, remember to extend content globs.
e2e/solid-start/query-integration/tailwind.config.mjs (1)
1-8
: LGTMMatches the basic suite; no issues.
e2e/solid-start/basic-solid-query/src/styles/app.css (1)
1-8
: LGTM!Standard Tailwind CSS setup with appropriate directives and base body styling.
packages/solid-router-ssr-query/tsconfig.json (1)
1-8
: LGTM!TypeScript configuration correctly sets up Solid JSX support with appropriate compiler options and includes.
packages/solid-router-ssr-query/README.md (1)
1-38
: LGTM!Clear and concise documentation with appropriate installation instructions and usage example.
e2e/solid-start/basic-solid-query/tests/app.spec.ts (1)
12-18
: LGTM!User navigation test uses complete, stable text selectors and appropriate assertions.
e2e/solid-start/basic-solid-query/tests/setup/global.teardown.ts (1)
1-6
: LGTM!Standard teardown pattern consistent with other e2e projects in the monorepo.
e2e/solid-start/query-integration/tests/app.spec.ts (1)
1-34
: LGTM!Well-structured e2e tests with stable data-testid selectors and clear validation of SSR query streaming behavior for both synchronous and asynchronous scenarios.
e2e/solid-start/query-integration/src/routes/index.tsx (1)
1-13
: LGTM!Clean file-based route implementation with correct usage of TanStack Solid Router APIs.
e2e/solid-start/basic-solid-query/src/routes/index.tsx (1)
1-13
: LGTM!Clean file-based route implementation following the same pattern as other routes in the project.
e2e/solid-start/basic-solid-query/src/routes/posts.index.tsx (1)
1-9
: LGTM!The index route is correctly structured for the
/posts/
path with a simple placeholder component. This follows the file-based routing pattern used elsewhere in the codebase.e2e/solid-start/basic-solid-query/src/routes/users.index.tsx (1)
1-9
: LGTM!The index route is correctly structured for the
/users/
path with a simple placeholder component, following the same pattern as the posts index route.e2e/solid-start/query-integration/vite.config.ts (1)
1-14
: LGTM!The Vite configuration correctly wires TypeScript path resolution, TanStack Start integration, and Solid SSR support. The plugin order is appropriate with
tsConfigPaths
first to ensure path resolution works for subsequent plugins.e2e/solid-start/basic-solid-query/tests/setup/global.setup.ts (1)
1-6
: LGTM!The global setup correctly initializes the dummy e2e server using the package name. Error handling is implicit through async/await propagation to the test runner, which is appropriate for test infrastructure.
e2e/solid-start/query-integration/src/router.tsx (1)
6-26
: LGTM!The router factory correctly configures the QueryClient with client-side-only
experimental_prefetchInRender
to avoid hydration mismatches, and properly integrates SSR query support. The setup follows the established pattern from related e2e projects.e2e/solid-start/basic-solid-query/src/routes/deferred.tsx (2)
5-24
: LGTM!The deferred query implementation correctly demonstrates SSR query integration with:
- Query prefetching in the loader to start fetching early
- Proper Suspense boundary for loading states
- Query options following TanStack Query patterns
26-54
: LGTM!The component structure is well-designed:
- Suspense boundary with appropriate fallback
- Local state (counter) demonstrates client-side interactivity during deferred loading
- The
DeferredQuery
component correctly usesuseQuery
and handles the data display- Line 51's
new Date()
wrapper handles both Date objects and serialized date strings across SSR boundariese2e/solid-start/basic-solid-query/src/router.tsx (1)
8-30
: LGTM!The router factory is properly configured with:
- Client-side-only
experimental_prefetchInRender
to prevent hydration mismatches- QueryClient context wiring for route loaders
- Default error and not-found components for comprehensive error handling
- SSR query integration setup
The implementation follows best practices and is consistent with the established patterns.
e2e/solid-start/basic-solid-query/playwright.config.ts (1)
1-39
: LGTM!The Playwright configuration is properly structured with:
- Dynamic port allocation from e2e utilities
- Global setup/teardown for test lifecycle management
- Server reuse optimization for local development (line 29)
- Single worker to avoid concurrency issues
- Comprehensive webServer configuration with proper environment variables
The webServer command (line 27) is complex but functional, correctly setting up environment variables for both build and start phases.
e2e/solid-start/query-integration/src/routes/useQuery.tsx (1)
7-12
: LGTM — loader prefetch + useQuery wiring is correct.Prefetch ensures SSR/hydration consistency; static qOptions keeps keys stable.
Also applies to: 14-24
packages/solid-router-ssr-query/vite.config.ts (1)
4-4
: No action needed—JSON import is properly supported.The verification confirms
resolveJsonModule: true
is enabled across the project's TypeScript configuration. The JSON import at line 4 will work correctly at runtime without requiringcreateRequire
.packages/solid-router-ssr-query/eslint.config.js (1)
3-12
: Based on the official documentation for eslint-plugin-solid, the TypeScript config is intended to be spread directly into a configuration object alongside other keys likefiles
andlanguageOptions
. This pattern indicates the preset exports a single configuration object, not an array.The current code in the PR follows the documented usage pattern. While flat configs are also available as
plugin.configs['flat/recommended']
andplugin.configs['flat/typescript']
after importing the plugin itself, the standard import fromeslint-plugin-solid/configs/typescript
behaves as shown in the official examples—as an object suitable for spreading.The review comment is incorrect and adds unnecessary complexity.
The proposed normalization pattern assumes a potential but undocumented array export. The official documentation consistently demonstrates the object spread pattern used in the current PR code, which is the correct approach.
Likely an incorrect or invalid review comment.
e2e/solid-start/query-integration/playwright.config.ts (1)
6-6
: Based on my verification:No issues found — the JSON import attributes syntax is properly supported.
Playwright officially requires Node.js latest 20.x, 22.x or 24.x, and the
with { type: 'json' }
syntax is supported in Node.js since version 20.10. Your TypeScript config fore2e/solid-start/query-integration/
hasresolveJsonModule: true
andmoduleResolution: "Bundler"
, which are properly configured for this syntax.The code in the Playwright config is both TypeScript-compatible and Node.js-compatible with modern versions that your project likely targets.
e2e/solid-start/query-integration/src/routeTree.gen.ts (1)
1-104
: Autogenerated file — skipping review.Based on learnings
e2e/solid-start/basic-solid-query/src/routeTree.gen.ts (1)
1-304
: Autogenerated file — skipping review.Based on learnings
packages/solid-router-ssr-query/package.json (2)
45-55
: Manual verification needed: Confirm the build outputsdist/cjs/index.d.cts
.The package references
.d.cts
in its exports for CJS types, which is consistent across the entire monorepo. However, because the actual build output depends on the external@tanstack/config/vite
tool and the sandbox cannot execute builds, this requires verification by running:npm run build fd index.d.cts dist/cjsOr by checking the published npm package to confirm
.d.cts
files are included.
63-65
: Update Node engine to at least >=14.18.0, not >=18.Based on the actual dependencies in the package.json:
- vite-plugin-solid v2.11.8 requires Node >= 14.18.0
- solid-js 1.9.x requires Node >= 8
The current
"node": ">=12"
is outdated and should be updated to"node": ">=14.18.0"
to meet the vite-plugin-solid requirement. However, updating to>=18
as suggested exceeds what the dependencies require."engines": { - "node": ">=12" + "node": ">=14.18.0" },Likely an incorrect or invalid review comment.
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, | ||
{ rel: 'icon', href: '/favicon.ico' }, | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove invalid color attribute from manifest link.
does not support a color attribute. Use a meta name="theme-color" or mask-icon link if needed.- { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'manifest', href: '/site.webmanifest' },
+ // Optional page color:
+ // { rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#ffffff' },
+ // Or:
+ // { name: 'theme-color', content: '#ffffff' },
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
{ rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, | |
{ rel: 'icon', href: '/favicon.ico' }, | |
], | |
{ rel: 'manifest', href: '/site.webmanifest' }, | |
// Optional page color: | |
// { rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#ffffff' }, | |
// Or: | |
// { name: 'theme-color', content: '#ffffff' }, | |
{ rel: 'icon', href: '/favicon.ico' }, | |
], |
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/routes/__root.tsx around lines 53 to
55, the manifest link entry includes an invalid color attribute; remove the
color property from the manifest link object and, if a theme color is required,
add a meta tag with name="theme-color" and the desired color (or use a mask-icon
link) in the document head instead.
GET: async ({ request }) => { | ||
console.info('Fetching users... @', request.url) | ||
const res = await axios.get<Array<User>>(`${queryURL}/users`) | ||
const list = res.data.slice(0, 10) | ||
return json( | ||
list.map((u) => ({ id: u.id, name: u.name, email: u.email })), | ||
) | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Add error handling (and timeout) to avoid unhandled 500s from upstream failures.
The GET handler can throw on network errors. Wrap in try/catch and return a controlled error. Optional: set a timeout.
Apply:
GET: async ({ request }) => {
console.info('Fetching users... @', request.url)
- const res = await axios.get<Array<User>>(`${queryURL}/users`)
- const list = res.data.slice(0, 10)
- return json(
- list.map((u) => ({ id: u.id, name: u.name, email: u.email })),
- )
+ try {
+ const res = await axios.get<Array<User>>(`${queryURL}/users`, {
+ timeout: 5000,
+ })
+ const list = res.data.slice(0, 10)
+ return json(
+ list.map((u) => ({ id: u.id, name: u.name, email: u.email })),
+ )
+ } catch (e) {
+ console.error('Failed to fetch users:', e)
+ return json({ error: 'Failed to fetch users' }, { status: 502 })
+ }
},
Also confirm these envs are set in test runs:
🏁 Script executed:
#!/bin/bash
rg -nP "(VITE_NODE_ENV|VITE_EXTERNAL_PORT)" -S -g "e2e/**"
Length of output: 16936
🏁 Script executed:
#!/bin/bash
# Get the actual code at lines 15-22 of the file
sed -n '15,22p' e2e/solid-start/basic-solid-query/src/routes/api.users.ts
Length of output: 318
🏁 Script executed:
#!/bin/bash
# Get broader context around the handler to understand the complete function
sed -n '1,30p' e2e/solid-start/basic-solid-query/src/routes/api.users.ts
Length of output: 765
Add error handling to the GET handler to prevent unhandled 500s from network failures.
The code currently has no error handling for the axios call on line 17. Network errors will propagate as unhandled exceptions, returning 500 status. Wrap in try/catch, set a timeout, and return a controlled 502 error.
GET: async ({ request }) => {
console.info('Fetching users... @', request.url)
- const res = await axios.get<Array<User>>(`${queryURL}/users`)
- const list = res.data.slice(0, 10)
- return json(
- list.map((u) => ({ id: u.id, name: u.name, email: u.email })),
- )
+ try {
+ const res = await axios.get<Array<User>>(`${queryURL}/users`, {
+ timeout: 5000,
+ })
+ const list = res.data.slice(0, 10)
+ return json(
+ list.map((u) => ({ id: u.id, name: u.name, email: u.email })),
+ )
+ } catch (e) {
+ console.error('Failed to fetch users:', e)
+ return json({ error: 'Failed to fetch users' }, { status: 502 })
+ }
},
Environment variables VITE_NODE_ENV
and VITE_EXTERNAL_PORT
are confirmed configured in the test setup (e.e./solid-start/basic-solid-query/playwright.config.ts).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
GET: async ({ request }) => { | |
console.info('Fetching users... @', request.url) | |
const res = await axios.get<Array<User>>(`${queryURL}/users`) | |
const list = res.data.slice(0, 10) | |
return json( | |
list.map((u) => ({ id: u.id, name: u.name, email: u.email })), | |
) | |
}, | |
GET: async ({ request }) => { | |
console.info('Fetching users... @', request.url) | |
try { | |
const res = await axios.get<Array<User>>(`${queryURL}/users`, { | |
timeout: 5000, | |
}) | |
const list = res.data.slice(0, 10) | |
return json( | |
list.map((u) => ({ id: u.id, name: u.name, email: u.email })), | |
) | |
} catch (e) { | |
console.error('Failed to fetch users:', e) | |
return json({ error: 'Failed to fetch users' }, { status: 502 }) | |
} | |
}, |
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/routes/api.users.ts around lines 15 to
22, the GET handler calls axios.get without error handling or a timeout which
lets network failures bubble up as unhandled 500s; wrap the axios call and
response mapping in a try/catch, add a timeout option to the axios request (e.g.
3–5s) and on catch log the error and return a controlled JSON response with an
appropriate error message and HTTP status 502 (using the existing json(...)
response helper with the status override).
to="/posts/$postId/deep" | ||
params={{ | ||
postId: postQuery.data?.id ?? '', | ||
}} | ||
activeProps={{ class: 'text-black font-bold' }} | ||
class="inline-block py-1 text-blue-800 hover:text-blue-600" | ||
> | ||
Deep View | ||
</Link> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Fix broken Link target; and avoid linking with empty postId.
The deep route file in this app is posts_.$postId.deep.tsx (path '/posts_/$postId/deep'), but this Link points to '/posts/$postId/deep'. Also, it renders with postId '' before data is ready.
Apply:
- <Link
- to="/posts/$postId/deep"
- params={{
- postId: postQuery.data?.id ?? '',
- }}
- activeProps={{ class: 'text-black font-bold' }}
- class="inline-block py-1 text-blue-800 hover:text-blue-600"
- >
- Deep View
- </Link>
+ {postQuery.data && (
+ <Link
+ to="/posts_/$postId/deep"
+ params={{ postId: String(postQuery.data.id) }}
+ activeProps={{ class: 'text-black font-bold' }}
+ class="inline-block py-1 text-blue-800 hover:text-blue-600"
+ >
+ Deep View
+ </Link>
+ )}
Confirm the intended route path in:
- e2e/solid-start/basic-solid-query/src/routes/posts_.$postId.deep.tsx
🏁 Script executed:
#!/bin/bash
# Search for the deep route file mentioned in the review
find e2e/solid-start/basic-solid-query/src/routes -name "*deep*" -type f
Length of output: 68
🏁 Script executed:
#!/bin/bash
# List all route files in the posts directory to understand structure
fd -e tsx -e ts e2e/solid-start/basic-solid-query/src/routes | grep -i post | head -20
Length of output: 481
🏁 Script executed:
#!/bin/bash
# Check the actual file being reviewed for context on postQuery and Link
cat e2e/solid-start/basic-solid-query/src/routes/posts.\$postId.tsx | head -50
Length of output: 1142
🏁 Script executed:
#!/bin/bash
# Search for other references to the deep route to see if this is isolated
rg -n "posts.*deep" e2e/solid-start/basic-solid-query/src --type tsx --type ts
Length of output: 27
🏁 Script executed:
#!/bin/bash
# Check the deep route file to understand its structure
cat e2e/solid-start/basic-solid-query/src/routes/posts_.\$postId.deep.tsx
Length of output: 1098
Fix broken Link target path and prevent linking with missing postId.
The deep route is declared as /posts_/$postId/deep
(with underscore in Solid Start file-based routing), but this Link points to /posts/$postId/deep
. Additionally, the Link renders unconditionally with an empty postId when postQuery.data
is undefined.
Apply:
- <Link
- to="/posts/$postId/deep"
- params={{
- postId: postQuery.data?.id ?? '',
- }}
- activeProps={{ class: 'text-black font-bold' }}
- class="inline-block py-1 text-blue-800 hover:text-blue-600"
- >
- Deep View
- </Link>
+ {postQuery.data && (
+ <Link
+ to="/posts_/$postId/deep"
+ params={{ postId: String(postQuery.data.id) }}
+ activeProps={{ class: 'text-black font-bold' }}
+ class="inline-block py-1 text-blue-800 hover:text-blue-600"
+ >
+ Deep View
+ </Link>
+ )}
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/routes/posts.$postId.tsx around lines
26-34, the Link uses the wrong route path and can render with an empty postId;
change the to prop to "/posts_/$postId/deep" (matching the file-based route) and
prevent rendering/navigation when postId is missing by computing const postId =
postQuery.data?.id and either render the Link only when postId is truthy (e.g.,
{postId && <Link ... params={{ postId }} />}) or disable/omit the params and add
aria-disabled when postId is falsy so the Link never points to an empty id.
loader: async ({ context, params: { userId } }) => { | ||
await context.queryClient.ensureQueryData(userQueryOptions(userId)) | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Map 404s to notFound() so notFoundComponent renders (ensure status is preserved).
Errors from ensureQueryData
currently become route errors, not 404s. Wrap and throw notFound()
on 404 to hit notFoundComponent
.
-import { ErrorComponent, createFileRoute } from '@tanstack/solid-router'
+import { ErrorComponent, createFileRoute, notFound } from '@tanstack/solid-router'
export const Route = createFileRoute('/users/$userId')({
loader: async ({ context, params: { userId } }) => {
- await context.queryClient.ensureQueryData(userQueryOptions(userId))
+ try {
+ await context.queryClient.ensureQueryData(userQueryOptions(userId))
+ } catch (e) {
+ const status = (e as any)?.response?.status ?? (e as any)?.status
+ if (status === 404) throw notFound()
+ throw e
+ }
},
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx around lines 9
to 11, errors from context.queryClient.ensureQueryData are becoming route errors
instead of rendering the notFoundComponent; wrap the ensureQueryData call in a
try/catch, detect 404s by checking error.status === 404 or
error.response?.status === 404, and when detected throw notFound() (imported
from 'solid-start') so the notFoundComponent renders and the 404 status is
preserved; for non-404 errors rethrow the original error.
notFoundComponent: () => { | ||
return <NotFound>User not found</NotFound> | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
notFoundComponent only triggers on notFound() — verify after applying the loader change.
After implementing the loader change above, confirm that requesting a non-existent user renders this component.
🏁 Script executed:
# Expect: "User not found" NotFound UI
# Example (adjust URL/port to your e2e env):
curl -i http://localhost:<port>/users/999999
Length of output: 50
I need to inspect the codebase to verify the loader implementation and understand how the notFoundComponent
is supposed to trigger. Let me explore the file structure and the loader logic.
🏁 Script executed:
#!/bin/bash
# Examine the full route file to see the loader implementation
cat "e2e/solid-start/basic-solid-query/src/routes/users.\$userId.tsx"
Length of output: 1114
I can see the loader currently doesn't call notFound()
. Let me inspect the userQueryOptions
function to understand how it handles missing users:
🏁 Script executed:
#!/bin/bash
# Find and examine the userQueryOptions function
find e2e/solid-start/basic-solid-query -name "*users*" -type f | head -20
Length of output: 352
🏁 Script executed:
#!/bin/bash
# Examine the userQueryOptions function
cat "e2e/solid-start/basic-solid-query/src/utils/users.tsx"
Length of output: 875
🏁 Script executed:
#!/bin/bash
# Examine the API endpoint that fetches individual users
cat "e2e/solid-start/basic-solid-query/src/routes/api/users.\$id.ts"
Length of output: 935
Loader must catch the query error and call notFound()
to trigger the notFoundComponent
.
The current loader doesn't handle the error thrown by ensureQueryData()
. When a non-existent user is requested, the API returns a 404, but the loader allows the error to propagate uncaught rather than calling notFound()
.
The loader needs modification:
loader: async ({ context, params: { userId } }) => {
try {
await context.queryClient.ensureQueryData(userQueryOptions(userId))
} catch {
throw new NotFoundError()
}
},
Or use solid-router's notFound()
function directly if available. Once this change is applied, the notFoundComponent
will render for missing users.
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/routes/users.$userId.tsx around lines
14 to 16, the loader does not catch errors from ensureQueryData and so a 404
from the API bubbles up instead of rendering the notFoundComponent; update the
loader to wrap the ensureQueryData call in a try/catch and on error call the
router's notFound() (or throw a NotFoundError) so the notFoundComponent is
triggered for missing users.
const tags = [ | ||
{ title }, | ||
{ name: 'description', content: description }, | ||
{ name: 'keywords', content: keywords }, | ||
{ name: 'twitter:title', content: title }, | ||
{ name: 'twitter:description', content: description }, | ||
{ name: 'twitter:creator', content: '@tannerlinsley' }, | ||
{ name: 'twitter:site', content: '@tannerlinsley' }, | ||
{ name: 'og:type', content: 'website' }, | ||
{ name: 'og:title', content: title }, | ||
{ name: 'og:description', content: description }, | ||
...(image | ||
? [ | ||
{ name: 'twitter:image', content: image }, | ||
{ name: 'twitter:card', content: 'summary_large_image' }, | ||
{ name: 'og:image', content: image }, | ||
] | ||
: []), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meta tags with undefined content values will be included.
When description
or keywords
are not provided, their corresponding meta tags will have content: undefined
. This could result in invalid or empty meta tags in the rendered HTML.
Apply this diff to filter out tags with undefined content values:
const tags = [
{ title },
{ name: 'description', content: description },
{ name: 'keywords', content: keywords },
{ name: 'twitter:title', content: title },
{ name: 'twitter:description', content: description },
{ name: 'twitter:creator', content: '@tannerlinsley' },
{ name: 'twitter:site', content: '@tannerlinsley' },
{ name: 'og:type', content: 'website' },
{ name: 'og:title', content: title },
{ name: 'og:description', content: description },
...(image
? [
{ name: 'twitter:image', content: image },
{ name: 'twitter:card', content: 'summary_large_image' },
{ name: 'og:image', content: image },
]
: []),
- ]
+ ].filter(tag => {
+ if ('title' in tag) return true
+ return tag.content !== undefined
+ })
return tags
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/utils/seo.ts around lines 9–27, the
tags array currently includes entries whose content may be undefined (e.g.,
description, keywords), producing invalid meta tags; after constructing the tags
array, filter out any tag objects that have a content property equal to
undefined and also ensure the title-only object is kept only when title is
defined — i.e., remove tags where ('content' in tag) and tag.content ===
undefined, and drop the title object if title is falsy.
{ name: 'twitter:creator', content: '@tannerlinsley' }, | ||
{ name: 'twitter:site', content: '@tannerlinsley' }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded personal Twitter handles in e2e test utility.
These lines hardcode @tannerlinsley
as the Twitter creator and site. Since this is an e2e test utility (not example code), these values should either be parameterized or use generic test values.
Apply this diff to make the Twitter handles configurable:
export function seo(params: {
title: string
description?: string
keywords?: string
image?: string
+ twitterCreator?: string
+ twitterSite?: string
}) {
- const { title, description, keywords, image } = params
+ const { title, description, keywords, image, twitterCreator, twitterSite } = params
const tags = [
{ title },
{ name: 'description', content: description },
{ name: 'keywords', content: keywords },
{ name: 'twitter:title', content: title },
{ name: 'twitter:description', content: description },
- { name: 'twitter:creator', content: '@tannerlinsley' },
- { name: 'twitter:site', content: '@tannerlinsley' },
+ { name: 'twitter:creator', content: twitterCreator },
+ { name: 'twitter:site', content: twitterSite },
{ name: 'og:type', content: 'website' },
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/utils/seo.ts around lines 15-16, the
twitter:creator and twitter:site entries are hardcoded to '@tannerlinsley';
change them to configurable values by adding parameters (or reading
environment/config) such as twitterCreator and twitterSite to the SEO utility
function and use those values instead of literal strings, provide sensible
defaults for tests (e.g., '@test' or an empty handle), and update any
callers/tests to pass the test-specific handles or rely on the defaults.
axios | ||
.get<Array<User>>(DEPLOY_URL + '/api/users') | ||
.then((r) => r.data) | ||
.catch(() => { | ||
throw new Error('Failed to fetch users') | ||
}), | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t swallow HTTP status; map 404→notFound or rethrow with cause.
Catching and throwing a generic Error drops the 404, preventing route-level notFound handling.
Option A (prefer): translate 404 to notFound()
and rethrow others.
+import { notFound } from '@tanstack/solid-router'
...
- .then((r) => r.data)
- .catch(() => {
- throw new Error('Failed to fetch users')
- }),
+ .then((r) => r.data)
+ .catch((e) => {
+ const status = (e as any)?.response?.status ?? (e as any)?.status
+ if (status === 404) throw notFound()
+ throw new Error('Failed to fetch users', { cause: e })
+ }),
...
- .then((r) => r.data)
- .catch(() => {
- throw new Error('Failed to fetch user')
- }),
+ .then((r) => r.data)
+ .catch((e) => {
+ const status = (e as any)?.response?.status ?? (e as any)?.status
+ if (status === 404) throw notFound()
+ throw new Error('Failed to fetch user', { cause: e })
+ }),
Option B: remove the .catch(...)
blocks entirely and handle mapping to notFound()
in the route loader (see route comment).
Also applies to: 31-37
🤖 Prompt for AI Agents
In e2e/solid-start/basic-solid-query/src/utils/users.tsx around lines 19-25 (and
similarly 31-37), the current .catch replaces all errors with a generic Error
and drops HTTP status; update the error handling to map a 404 to notFound() and
rethrow other errors with their original cause; specifically, in the axios.get
promise replace the generic .catch(() => throw new Error(...)) with logic that
checks the axios error response status (if 404 call notFound() immediately),
otherwise rethrow the original error (or throw a new Error while preserving the
original error as the cause) so upstream route loaders can handle non-404
errors; alternatively remove these local .catch blocks and perform the
404→notFound mapping in the route loader as noted in the comment.
"test:unit": "exit 0; vitest", | ||
"test:unit:dev": "pnpm run test:unit --watch", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests are effectively disabled (exit 0; vitest
).
- "test:unit": "exit 0; vitest",
+ "test:unit": "vitest",
If this is intentional for a draft, add a TODO and re-enable before merge.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
"test:unit": "exit 0; vitest", | |
"test:unit:dev": "pnpm run test:unit --watch", | |
"test:unit": "vitest", | |
"test:unit:dev": "pnpm run test:unit --watch", |
🤖 Prompt for AI Agents
In packages/solid-router-ssr-query/package.json around lines 36-37, the
"test:unit" script is prefixed with "exit 0;" which short-circuits and disables
unit tests; remove the "exit 0;" so the script simply runs "vitest" (i.e. change
to "test:unit": "vitest"), and if the disabling was intentional leave the
current line but add a TODO comment in the PR/issue tracker and mark tests to be
re-enabled before merge so CI still runs real tests.
"eslint-plugin-solid": "^0.14.5" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move eslint plugin to devDependencies to avoid shipping it to consumers.
"dependencies": {
- "@tanstack/router-ssr-query-core": "workspace:*",
- "eslint-plugin-solid": "^0.14.5"
+ "@tanstack/router-ssr-query-core": "workspace:*"
},
"devDependencies": {
+ "eslint-plugin-solid": "^0.14.5",
🤖 Prompt for AI Agents
In packages/solid-router-ssr-query/package.json around lines 68-69, the
eslint-plugin-solid entry is listed under dependencies and should be moved to
devDependencies so it isn't shipped to consumers; remove the
"eslint-plugin-solid": "^0.14.5" line from dependencies and add the same entry
under devDependencies (keeping the version), then run your package manager
(npm/yarn/pnpm) to update node_modules and lockfile so the change is reflected.
197bd86
to
acba783
Compare
Supersedes
Summary by CodeRabbit
New Features
Tests